package com.nx.vip.javacore.reflection;

import com.nx.vip.javacore.reflection.pojo.Person;
import com.nx.vip.javacore.reflection.pojo.User;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;

/**
 * 获取Class文件的方式
 * 1、类名.class
 * 2、Class.forName //反射
 * 3、对象.getClass()
 * 4、通过类加载器.loadClass()
 */
public class CoreMain {
    public static void main(String[] args) throws Exception{

        //1、 不会堆类初始化
        Class<Person> clazz01 = Person.class;
        System.out.println(clazz01);
        //2、MySQL
        Class<?> clazz02 = Class.forName("com.nx.vip.javacore.reflection.pojo.Person");
        System.out.println(clazz02);
        //3、
        Class<? extends Person> clazz03 = new Person().getClass();
        System.out.println(clazz03);
        //4、
        Class<?> clazz04 = CoreMain.class.getClassLoader().loadClass("com.nx.vip.javacore.reflection.pojo.Person");
        System.out.println(clazz04);

        //通过Clazz获取基本信息；属性信息；方法信息；注解信息
        /**
         * 获取的是类的修饰符
         */
        System.out.println("--------------");
        int modifiers = clazz01.getModifiers();
        System.out.println(modifiers);
        System.out.println(clazz01.getPackage());
        System.out.println(clazz01.getName());
        System.out.println(clazz01.getSimpleName());
        System.out.println(clazz01.getClassLoader());
        System.out.println(clazz01.getInterfaces());
        System.out.println(clazz01.getSuperclass());
        System.out.println(clazz01.getAnnotations());

        /**
         * 属性基本操作
         */
        System.out.println("--------------");
        Class<User> clazz = User.class;
        User user = clazz.newInstance(); // 反射调用的无参的构造方法

        Field[] fields = clazz.getFields(); //所有public字段、包括继承来的
        for(Field field:fields){
            System.out.println(field.getName());
        }
        System.out.println("--------------");
        Field[] declaredFields = clazz.getDeclaredFields();//获取当前类中定义的
        for(Field field:declaredFields){
            System.out.println(field.getName());
        }
        System.out.println("--------------");
        Field addField = clazz.getDeclaredField("address");
        addField.setAccessible(true); //设置字段的强制访问
        addField.set(user,"北京西三旗奈学");
        System.out.println(user.getAddress());
        System.out.println("--------------");

        Field nationalty = clazz.getDeclaredField("nationalty");
        nationalty.set(null,"中国");
        System.out.println(user.nationalty);
        System.out.println("--------------");
        // 构造函数
        clazz.getDeclaredConstructors();
        Constructor<User> declaredConstructor = clazz.getDeclaredConstructor(String.class, String.class);
        declaredConstructor.setAccessible(true);
        User user1 = declaredConstructor.newInstance("idCard", "address");
        User user2 = clazz.newInstance(); //通过无参的构造函数反射出来的，无参的构造函数需要是public
        System.out.println(user1);

        System.out.println("--------------");
        SingleDemo instance1 = SingleDemo.getInstance();
        SingleDemo instance2 = SingleDemo.getInstance();
        System.out.println(instance1==instance2);

////        Constructor<? extends SingleDemo> constructor = instance1.getClass().getDeclaredConstructor();
////        constructor.setAccessible(true);
////        SingleDemo instance3 = constructor.newInstance();
////        System.out.println(instance1==instance3);//false

//        System.out.println("--------------");
//        ClassPathXmlApplicationContext con = new ClassPathXmlApplicationContext("spring-ioc.xml");
//        Object user2 = con.getBean("user");
//        System.out.println(user2);

        /**
         * class.newInstance();底层使用的是反射出的无参的构造器，需要可见
         * Constructor.newInstance()’；任何的构造器都能够构造出一个实例，private也可以
         */


    }
}
